package com.astro.backend;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.InputStream;
import java.io.StringWriter;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;

import com.astro.backend.business.dao.Bill;
import com.astro.backend.business.dao.BillSummary;
import com.astro.backend.business.dao.CurrentBillCharges;
import com.astro.backend.business.dao.ProrationDetails;
import com.astro.backend.business.dao.RewardSummary;
import com.checkfree.isolutions.customer.persist.Account;
import com.checkfree.isolutions.customer.persist.AccountHomeImpl;
import com.checkfree.isolutions.customer.persist.Merchant;
import com.checkfree.isolutions.customer.persist.MerchantHomeImpl;
import com.checkfree.isolutions.persist.PersistServer;
import com.checkfree.isolutions.statement.StatementSection;
import com.checkfree.isolutions.statement.persist.Statement;
import com.checkfree.isolutions.statement.persist.StatementHomeImpl;

public class HtmlGenerator {
	
//	public static final String MERCHANT = "AstroBill";
	public static final String MERCHANT = "ASTRO";
	
	public static final String CONFIG_FILE = "/properties/HtmlGenerator.properties";
	public static final java.util.Properties appConfig =  new java.util.Properties();
	
	private String htmlPath;
	private String statusFilePathIn="";
	private ArrayList arAccounts = new ArrayList();
	private List<Bill> lstStatusAndDate = new ArrayList<>();
	private List<String> lstDate = new ArrayList<>();
	private List<Date> lstTempDate = new ArrayList<>();
	private SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yy");
	private SimpleDateFormat sdf2  = new SimpleDateFormat("yyyy,MM,dd");
	
	public HtmlGenerator() {
		try {
			InputStream stream = this.getClass().getResourceAsStream(
					CONFIG_FILE);
			if (stream != null) {
				appConfig.load(stream);
			} else {
				throw new Exception("input stream is null");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		statusFilePathIn = appConfig.getProperty("file.path.in");
		htmlPath =appConfig.getProperty("html.path");
	}
	
    public static void main( String[] args )throws Throwable {
		SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
		
    	String stmtDateStr = "20150331";
    	Date statementDate = formatter.parse(stmtDateStr);
    	
    	
    	HtmlGenerator htmlGen = new HtmlGenerator();
    	htmlGen.getAccountList();
    	htmlGen.genHtml();
//    	NumberFormat nf = new DecimalFormat("0.00");
//        System.out.println(nf.format(100.22));
//
//    	new HtmlGenerator().test();

    	
    }
    public void putdata (Statement stmt) throws Exception{
    	SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
    	VelocityEngine ve = new VelocityEngine();
        ve.init();
        Template t = ve.getTemplate( "./src/index.html" );
        VelocityContext context = new VelocityContext();
        
    	BillSummary billsum = setDataToBillSummary(stmt);
        
    	//put data to customer information
    	context.put("name", billsum.getAccountName());
    	context.put("addList", billsum.getAddList());
    	context.put("accountNumber", billsum.getAccountNumber());
    	context.put("stmtDate", new SimpleDateFormat("dd/MM/yyyy").format(stmt.getDate()));
    	context.put("month", new SimpleDateFormat("MMM yyyy").format(stmt.getDate()));
    	context.put("billingPeriod", billsum.getBillPeriod());
    	
        //put data to Your last bill

        context.put("previousbalance", billsum.getPreviousMontBalance());
        context.put("payment", billsum.getPayment());
        context.put("adjustments", billsum.getAdjustments());
        
        //put data to Your current bill
        
        context.put("overduecharges", billsum.getOverdueCharges());
        context.put("newCharges", billsum.getNewCharged());
        context.put("amountdue", billsum.getAmountDue());
        
        
        // put data to pay Date
        context.put("paydate", billsum.getPayDate());
        
        CurrentBillCharges transaction = setDataToTransactionDetails(stmt);
        context.put("transaction", transaction);
        context.put("transcationTotal", transaction.getTotal());
        
        context.put("feeList", setDataToFeeCharges(stmt));
        
        //put data to Current Bill Charges
//        List<CurrentBillCharges> currentBillList = setDataToCurrentBill(stmt);
        
        Map<String, List<CurrentBillCharges>> chargeSections = new HashMap<String, List<CurrentBillCharges>>();
        List<CurrentBillCharges> lstCurrentBillCharges = setDataSmartCardToTransactionDetail(stmt, "CurrentBillChargesSection");
        List<CurrentBillCharges> lstSubscriptionChanges = setDataSmartCardToTransactionDetail(stmt, "SubscriptionChangesSection");
        List<ProrationDetails> lstProrationDetails = setDataToProrationDetails(lstCurrentBillCharges, lstSubscriptionChanges);
        context.put("lstProrationDetails", lstProrationDetails);
        context.put("currentBillList",lstCurrentBillCharges );
        context.put("subscriptionList",lstSubscriptionChanges);

//        context.put("lstStatusAndDate", lstStatusAndDate);

//        lstDate.add(minusMonth(sdf2.format(cal.getTime())));
		
//        context.put("lstDate", lstDate);

//        context.put("startDate",minusMonth(lstProrationDetails.get(0).getLstDate().get(0)));
//        context.put("endDate",minusMonth(lstProrationDetails.get(0).getLstDate().get(lstProrationDetails.get(0).getLstDate().size()-1)));
        
        //put data to tax and total
        context.put("tax", billsum.getTax());
        context.put("totalcharge", billsum.getTotalCharges());
        context.put("roundTotal", billsum.getRoundTotal());
        
        /*****************************GenChart**************************************/
        List<CurrentBillCharges> genChartList = new ArrayList<CurrentBillCharges>();
        genChartList.add(transaction);
//        for(int i =0;i<currentBillList.size();i++){
//        	genChartList.add(currentBillList.get(i));
//        }
//        clearString(genChartList);
        context.put("genChartList", genChartList);
        /*******************************************************************************/
        
        
        
        // Start Put data for Reward
        RewardSummary rewardSum = setDataToRewardSummary(stmt);
        
//        rewardSum.setExpiryMonth("May 2015");
//        rewardSum.setExpiryPoints("20");
//        rewardSum.setPointsEarned("11");
//        rewardSum.setPointsRedeemed("20");
//        rewardSum.setPreviousBalance("300");
//        rewardSum.setTotalNewBalance("200");
        
        context.put("rewardSum", rewardSum);
        // End Put data for Reward
        
        
        StringWriter writer = new StringWriter();
        t.merge( context, writer );
        
        BufferedWriter bwrite = null;
        try {
			
//	        File file = new File("D:/astro/astro 2/index_output.html");
	        
			String fullAccNo = stmt.getRootSection().getFieldText("FullAccNo");
			fullAccNo = fullAccNo.replaceAll("-", "");
			
	        File file = new File(htmlPath+fullAccNo+".html");
	        bwrite = new BufferedWriter(new FileWriter(file, false));
	        bwrite.write(writer.toString());
	        System.out.println("finish write file to "+ htmlPath+fullAccNo+".html");

        } catch (Exception e) {
        	e.printStackTrace();
        } finally {
        	bwrite.close();
        }
    }
    
    public BillSummary setDataToBillSummary(Statement stmt){

    	BillSummary billsum = new BillSummary();

    	StatementSection cfiRootSection = stmt.getRootSection();
    	

    	
    	StatementSection transactionDetailsSection = cfiRootSection.getSection("TransactionDetailsSection");
    	
    	/***********************get data***********************************/
    	
    	//get data for customer information
    	String accountName = cfiRootSection.getFieldText("AccountName");
    	
    	StatementSection addressSection = cfiRootSection.getSection("AddressSection");
    	int addressSectionCount = (int)addressSection.getSectionCount("RepeatSection");
    	List<String> addList = new ArrayList<String>();
    	for(int i=0;i<addressSectionCount;i++){
    		StatementSection repeatSection = addressSection.getRepeatSection("RepeatSection", i);
    		addList.add(repeatSection.getFieldText("Address"));
    	}
    	String accountNumber = cfiRootSection.getFieldText("FullAccNo");
    	String billPeriod = cfiRootSection.getFieldText("BillingPeriod");
    	
    	//get data for last bill
    	String prevMonthBalance 	= cfiRootSection.getFieldText("PrevMonthBalance");
		String payment = cfiRootSection.getFieldText("Payment");
		String adjustments 	= cfiRootSection.getFieldText("Adjustments");

		
		//get data for current bill
		String overDueAmt 	= cfiRootSection.getFieldText("OverDueAmt");
    	String amountCharged = cfiRootSection.getFieldText("NewCharges"); // confirm (amount charged)
		String amountDue 	= cfiRootSection.getFieldText("AmountDue");

    	
    	//get data for transaction

    	String dueDate 	= cfiRootSection.getFieldText("DueDate"); // Confirm
    	
    	//get data for Government Service Tax 
    	StatementSection totalSection = transactionDetailsSection.getSection("TotalSection");
    	String serviceTax = totalSection.getFieldText("ServiceTax"); //Confirm
    	
//    	StatementSection totalChargesSection = transactionDetailsSection.getSection("TotalChargesSection");
    	String totalCharge = totalSection.getFieldText("Total");
    	
    	//get data for Round Total
    	StatementSection roundTotalSection = transactionDetailsSection.getSection("RoundTotalSection");
    	String roundTotal = null;
    	if(roundTotalSection != null){
    		roundTotal = roundTotalSection.getFieldText("Amount");
    	}

    	/******************** set data ***********************************/   	
    	//customer information
    	billsum.setAccountName(accountName);
    	billsum.setAddList(addList);
    	billsum.setAccountNumber(accountNumber);
    	billsum.setBillPeriod(billPeriod);
    	
    	//Your last bill
    	billsum.setPreviousMontBalance(prevMonthBalance);
    	billsum.setAdjustments(adjustments);
    	billsum.setPayment(payment);
//    	billsum.setOverdueAmount(overDueAmt);
    	
    	//Your current bill
    	
    	billsum.setOverdueCharges(overDueAmt);
    	billsum.setNewCharged(amountCharged);
    	billsum.setAmountDue(amountDue);
    	
    	//transaction


    	
        billsum.setPayDate(dueDate);
        billsum.setTax(serviceTax);
        
        billsum.setRoundTotal(roundTotal);
        
        billsum.setTotalCharges(totalCharge);
        
    	return billsum;
    }


    public RewardSummary setDataToRewardSummary(Statement stmt){

    	RewardSummary rewardSum = new RewardSummary();

    	StatementSection cfiRootSection = stmt.getRootSection();
    	
    	StatementSection loyaltyPointSection = cfiRootSection.getSection("LoyaltyPointSection");
		if(loyaltyPointSection!=null){
			
			rewardSum.setPreviousBalance(loyaltyPointSection.getFieldText("PreviousBalance"));
			rewardSum.setPointsEarned(loyaltyPointSection.getFieldText("PointsEarned"));
			rewardSum.setPointsRedeemed(loyaltyPointSection.getFieldText("PointsRedeemed"));
			rewardSum.setTotalNewBalance(loyaltyPointSection.getFieldText("TotalNewBalance"));
			rewardSum.setExpiryMonth(loyaltyPointSection.getFieldText("ExpiryMonth"));
			rewardSum.setExpiryPoints(loyaltyPointSection.getFieldText("ExpiryPoints"));
		}

		
    	return rewardSum;
    }

//    NumberFormat nf = new DecimalFormat("0.00");
    public List<CurrentBillCharges> setDataToCurrentBill (Statement stmt){
    	
    	NumberFormat numFormat = new DecimalFormat("0.00");
    	StatementSection cfiRootSection = stmt.getRootSection();
		List<CurrentBillCharges> currentBillList = new ArrayList<CurrentBillCharges>();
    	if(cfiRootSection != null){
    		StatementSection transactionDetailsSection = cfiRootSection.getSection("TransactionDetailsSection");
    		if( transactionDetailsSection != null){
    			/*Test*/
    			
    			/*End Test*/
    			StatementSection currentBillChargesSection = transactionDetailsSection.getSection("CurrentBillChargesSection");
    			if(currentBillChargesSection != null){
    				boolean haveStar = false;
    				int smartCardRSectionCount = (int)currentBillChargesSection.getSectionCount("SmartCardRSection");
    				for(int i=0;i<smartCardRSectionCount;i++){
    				CurrentBillCharges curtBillCharge = new CurrentBillCharges();
    		
    				StatementSection smartCardRSection = currentBillChargesSection.getRepeatSection("SmartCardRSection", i);
    				if(smartCardRSection != null){
    					curtBillCharge.setSmartCardNo(smartCardRSection.getFieldText("SmartCardNo"));
    					int repeatSectionCount = (int)smartCardRSection.getSectionCount("RepeatSection");
    					List<Bill> billList = new ArrayList<Bill>();
    					float totalBillCharges = 0;
    					for(int j=0; j<repeatSectionCount;j++){
    						StatementSection repeatSection = smartCardRSection.getRepeatSection("RepeatSection", j);
    						Bill bill = new Bill();
    							if(repeatSection != null){
    								bill.setDescription(repeatSection.getFieldText("Description"));
    								bill.setAmount(repeatSection.getFieldText("Amount"));
    								bill.setPeriod(repeatSection.getFieldText("Period"));
    								bill.setStar(repeatSection.getFieldText("Star"));
    								if(!StringUtils.isEmpty(repeatSection.getFieldText("Star"))){
    									haveStar = true;
    								}
    								bill.setTotal(repeatSection.getFieldText("Total"));
    								
    								//String total = repeatSection.getFieldText("Total");
    								totalBillCharges = totalBillCharges + convertToInt(repeatSection.getFieldText("Amount"));
    								if(StringUtils.isEmpty(repeatSection.getFieldText("Description"))){
    									break;
    								}
    							}
    							billList.add(bill);
//    				    		curtBillCharge.setTotal(nf.format(totalBillCharges));
//    				    		curtBillCharge.setBillLst(billList);
//    				    		currentBillList.add(curtBillCharge);

    					}
    					if(haveStar){
    						curtBillCharge.setStar("*");
    					}
    					numFormat.format(totalBillCharges);
    					curtBillCharge.setTotal( numFormat.format(totalBillCharges));
//			    		curtBillCharge.setTotal(String.valueOf(totalBillCharges));
			    		curtBillCharge.setBillLst(billList);
			    		currentBillList.add(curtBillCharge);
    				}
    				}
    			}
    		}
    			
    		}

    	
    	return currentBillList;
    }
    
    public List<CurrentBillCharges> setDataSmartCardToTransactionDetail (Statement stmt, String sectionName){
    	StatementSection cfiRootSection = stmt.getRootSection();
		List<CurrentBillCharges> chargeList = new ArrayList<CurrentBillCharges>();
    	if(cfiRootSection != null){
    		StatementSection transactionDetailsSection = cfiRootSection.getSection("TransactionDetailsSection");
    		if( transactionDetailsSection != null){
    			StatementSection currentBillChargesSection = transactionDetailsSection.getSection(sectionName);
    			if(currentBillChargesSection != null){
    				int smartCardRSectionCount = (int)currentBillChargesSection.getSectionCount("SmartCardRSection");
    				
    				for(int i=0;i<smartCardRSectionCount;i++){
    					CurrentBillCharges charge = new CurrentBillCharges();
	    		
	    				StatementSection smartCardRSection = currentBillChargesSection.getRepeatSection("SmartCardRSection", i);
	    				if(smartCardRSection != null){
	    					charge.setSmartCardNo(smartCardRSection.getFieldText("SmartCardNo"));
	    					int repeatSectionCount = (int)smartCardRSection.getSectionCount("RepeatSection");
	    					List<Bill> billList = new ArrayList<Bill>();
	    					for(int j=0; j<repeatSectionCount;j++){
	    						StatementSection repeatSection = smartCardRSection.getRepeatSection("RepeatSection", j);
	    						Bill bill = new Bill();
    							if(repeatSection != null){
    								bill.setDescription(repeatSection.getFieldText("Description"));
    								bill.setAmount(repeatSection.getFieldText("Amount"));
    								bill.setPeriod(repeatSection.getFieldText("Period"));
    								bill.setStar(repeatSection.getFieldText("Star"));
    								bill.setTotal(repeatSection.getFieldText("Total"));
    								bill.setStatus(repeatSection.getFieldText("Status")); 
    								bill.setGstRM(repeatSection.getFieldText("GST"));
    								
    								if(StringUtils.isEmpty(repeatSection.getFieldText("Description"))){
    									break;
    								}
    							}
    							billList.add(bill);
	
	    					}
				    		charge.setBillLst(billList);
				    		chargeList.add(charge);
	    				}
    				}
    			}
    		}
    			
    		}

    	System.out.println(sectionName + ":" + chargeList.size());
    	return chargeList;
    }
    
    public List<Bill> setDataToFeeCharges(Statement stmt){
    	List<Bill> billList = new ArrayList<Bill>();
    	StatementSection cfiRootSection = stmt.getRootSection();
    	if(cfiRootSection != null){
    		StatementSection transactionDetailsSection = cfiRootSection.getSection("TransactionDetailsSection");
    		if (transactionDetailsSection != null ){
    			
    			CurrentBillCharges summary = new CurrentBillCharges();
				StatementSection summarySection = transactionDetailsSection.getSection("FeesSection");
				if(summarySection != null){
						int repeatSectionCount = (int)summarySection.getSectionCount("RepeatSection");
						for (int i = 0;i<repeatSectionCount;i++){
							Bill bill = new Bill();
							StatementSection repeatSection = summarySection.getRepeatSection("RepeatSection", i);
							bill.setDescription(repeatSection.getFieldText("Description"));
							bill.setAmount(repeatSection.getFieldText("Amount"));
							bill.setPeriod(repeatSection.getFieldText("Period"));
							bill.setTotal(repeatSection.getFieldText("Total"));
							billList.add(bill);
						}
				}
    		}
    	}
    	System.out.println("Fees:" + billList.size());
    	return billList;
    }
    
    public CurrentBillCharges setDataToTransactionDetails(Statement stmt){
    	CurrentBillCharges transaction = new CurrentBillCharges();
    	StatementSection cfiRootSection = stmt.getRootSection();
    	List<Bill> billList = new ArrayList<Bill>();
    	if(cfiRootSection != null){
    		StatementSection transactionDetailsSection = cfiRootSection.getSection("TransactionDetailsSection");
    		if (transactionDetailsSection != null ){
    			
    			StatementSection overdueChargesSection = transactionDetailsSection.getSection("OverdueChargesSection");

				if (overdueChargesSection != null) {
					StatementSection totalOverdueCharges = overdueChargesSection
							.getSection("TotalOverdueCharges");
					if (totalOverdueCharges != null) {
						transaction.setTotal(overdueChargesSection
								.getFieldText("Total"));
					}

					int repeatSectionCountOv = (int) overdueChargesSection
							.getSectionCount("RepeatSection");
					for (int i = 0; i < repeatSectionCountOv; i++) {
						Bill bill = new Bill();
						StatementSection repeatSectionOv = overdueChargesSection
								.getRepeatSection("RepeatSection", i);
						bill.setDescription(repeatSectionOv
								.getFieldText("Transaction"));
						bill.setAmount(repeatSectionOv.getFieldText("Total"));
						bill.setTotal(repeatSectionOv.getFieldText("Total"));
						billList.add(bill);
					}
					StatementSection paymentSection = overdueChargesSection
							.getSection("PaymentSection");
					if (paymentSection != null) {
						int repeatSectionCount = (int) paymentSection
								.getSectionCount("RepeatSection");

						for (int i = 0; i < repeatSectionCount; i++) {
							Bill bill = new Bill();
							StatementSection repeatSection = paymentSection
									.getRepeatSection("RepeatSection", i);
							bill.setDescription(repeatSection
									.getFieldText("Description"));
							bill.setAmount(repeatSection.getFieldText("Amount"));
							bill.setPeriod(repeatSection.getFieldText("Period"));
							bill.setTotal(repeatSection.getFieldText("Total"));
							billList.add(bill);
						}
						transaction.setBillLst(billList);
					}
				}
    	
				//transaction.setSmartCardNo("Previous month balance");
    		}
    	}

    	return transaction;
    }
    public float convertToInt(String string){
    	string =string.replaceAll(" ", "");
    	string =string.replaceAll(",", "");
    	float number=0;
    	if(!StringUtils.isEmpty(string)){
    		number = Float.parseFloat(string);
    	}

    	return number;
    }
    public void clearString(List<CurrentBillCharges> chargeList){
    	for(int i=0;i<chargeList.size();i++){
    		chargeList.get(i).setTotal(removeJunkString(chargeList.get(i).getTotal()));
    		for(int j =0; j<chargeList.get(i).getBillLst().size();j++){
    			chargeList.get(i).getBillLst().get(j).setAmount(removeJunkString(chargeList.get(i).getBillLst().get(j).getAmount()));
    			chargeList.get(i).getBillLst().get(j).setTotal(removeJunkString(chargeList.get(i).getBillLst().get(j).getTotal()));
    		}
    	}
    }

	public String removeJunkString(String string) {
		if (!StringUtils.isEmpty(string)) {
			string = string.replaceAll("-", "");
			string = string.replaceAll(",", "");
			return string;
		} else {
			return "";
		}
	}
	
	public void getAccountList () {
		try {
	 
			File inDir = new File(statusFilePathIn);
			if (!inDir.isDirectory()) {
				throw new Exception (statusFilePathIn +" is not a valid directory path");
			}

			// process all files
			File [] inFiles = inDir.listFiles();
			arAccounts = new ArrayList();
			for (int i=0; i < inFiles.length; i++) {
				String strFilePath = inFiles[i].getAbsolutePath();
				System.out.println("HtmlGenerator.java strFilePath="+strFilePath);
				if(strFilePath==null){
					strFilePath="";
				}
				String strFileName = "";
				if(strFilePath.indexOf(".txt")>0){
					strFileName = strFilePath.substring(strFilePath.lastIndexOf("\\")+1,strFilePath.lastIndexOf("."));				
				}
				if(strFileName.startsWith("cycle")){
                    BufferedReader data = new BufferedReader(new FileReader(strFilePath));
                    //int lineNo = 0;
					String tempData="";

                    while(true){
                        tempData = data.readLine();
                        //lineNo++;
                        //System.out.println("ProcessMail.java tempData :" + tempData);
                        if (tempData=="" || tempData==null){
                            break;
                        }
						arAccounts.add(tempData);
						System.out.println("GenAccPdfV3.java getAccountList -> tempData :" + tempData);
					}//end of while(true)
					
                    data.close();
				}//end of if file name starts with cycle
			}//end of loop the folder
		} catch (Exception e) {
			e.printStackTrace();
			System.err.println("GenAccPdfV3 getAccountList Error reading file ");
			System.err.println(e.getMessage());
		}	
	 }//end getAccountList
	
	public void genHtml() throws Throwable {
		System.out.println("start genHtml");

		try {

			PersistServer.activate(MERCHANT);
			PersistServer.beginTransaction();

			Merchant theMerchant = MerchantHomeImpl.singleton().findByName(
					MERCHANT);
			if (theMerchant == null) {
				throw new Exception("unable to obtain Persist Merchant object");
			}
			for (int i = 0; i < arAccounts.size(); i++) {
				System.out.println("start process account number :"+arAccounts.get(i));
				String accountNo = arAccounts.get(i).toString().trim();
				Account account = AccountHomeImpl.singleton()
						.findByExternalKeyAndMerchant(
								accountNo,
								theMerchant);

				if (account != null) {
					Statement statement = StatementHomeImpl.singleton()
							.findTheLatestStatementForAccount(account);
					if(statement != null){
						putdata(statement);
					} else {
						System.out.println("This account does not have statement in db " + accountNo);
					}
				} else {
					System.out.println("This account is not existed in db " + accountNo);
				}

			}

		} catch (Exception ex) {
			ex.printStackTrace();
		} finally {
			try {
				PersistServer.commitTransaction();
				PersistServer.deactivate();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		System.out.println("genHtml end");

	}
	
	public void test () throws Exception{
    	SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
    	VelocityEngine ve = new VelocityEngine();
        ve.init();
        Template t = ve.getTemplate( "./src/test.txt" );
        VelocityContext context = new VelocityContext();
        
        context.put("c1","RM 0.00");
        context.put("c2","RM 0");
        context.put("c3","RM-0.70");
        context.put("c4",".");
        context.put("c5","01");
        
        
        StringWriter writer = new StringWriter();
        t.merge( context, writer );
        
        BufferedWriter bwrite = null;
        try {
	        File file = new File("D:/test_out.txt");
	        bwrite = new BufferedWriter(new FileWriter(file, false));
	        bwrite.write(writer.toString());
	        System.out.println("Finished.");
        } catch (Exception e) {
        	e.printStackTrace();
        } finally {
        	bwrite.close();
        }
    }
	
	public List<ProrationDetails> setDataToProrationDetails (List<CurrentBillCharges> lstCurrentBillCharges, List<CurrentBillCharges> lstSubscriptionChanges){
		HashMap<String, List<Bill>> currentBillChargesMap = new HashMap<String, List<Bill>>();
		HashMap<String, List<Bill>> subscriptionChangesMap = new HashMap<String, List<Bill>>();
		List<ProrationDetails> lstProrationDetails = new ArrayList<>();
		for(int i=0; i< lstCurrentBillCharges.size(); i++){
			currentBillChargesMap.put(lstCurrentBillCharges.get(i).getSmartCardNo(), lstCurrentBillCharges.get(i).getBillLst());
		}
		for(int i = 0; i < lstSubscriptionChanges.size(); i ++ ){
			subscriptionChangesMap.put(lstSubscriptionChanges.get(i).getSmartCardNo(), lstSubscriptionChanges.get(i).getBillLst());
		}
		for(String smartCard : subscriptionChangesMap.keySet()){
			if(currentBillChargesMap.containsKey(smartCard)){
				ProrationDetails prorationDetails = new ProrationDetails();
				lstDate.clear();
				lstTempDate.clear();
				lstStatusAndDate.clear();
				prorationDetails.setSmartCardNo(smartCard);
				prorationDetails.setLstSubscriptionChanges(calculateGraphData(subscriptionChangesMap.get(smartCard)));
				prorationDetails.setLstCurrentBillCharges(calculateGraphData(currentBillChargesMap.get(smartCard)));
				calculateTotalAdjustment(prorationDetails);

				Collections.sort(lstTempDate);
		        Calendar cal = Calendar.getInstance();
		        cal.setTime(lstTempDate.get(1));
		        cal.add(Calendar.DATE, -30);
		        lstTempDate.add(cal.getTime());
		        Collections.sort(lstTempDate);
				for(int i =0; i<lstTempDate.size(); i++){
					if(!lstDate.contains(minusMonth(sdf2.format(lstTempDate.get(i))))){
						lstDate.add(minusMonth(sdf2.format(lstTempDate.get(i))));
					}
				}
				
				prorationDetails.setLstDate(lstDate);
				prorationDetails.setLstStatusAndDate(lstStatusAndDate);
				lstProrationDetails.add(prorationDetails);
//				getListDate(prorationDetails);
			}
		}
		return lstProrationDetails;
	}
	
	public List<Bill> calculateGraphData(List<Bill> lstBill) {
		List<Bill> resultList = new ArrayList<>();
		HashMap<String, Bill> billMap = new HashMap<>();
		for (int i = 0; i < lstBill.size(); i++) {
			if (billMap.containsKey(lstBill.get(i).getDescription())) {
				String amountBill = lstBill.get(i).getAmount();
				String amountMap = billMap.get(lstBill.get(i).getDescription())
						.getAmount();
				String periodBill = lstBill.get(i).getPeriod();
				String periodMap = billMap.get(lstBill.get(i).getDescription())
						.getPeriod();
				String statusBill = lstBill.get(i).getStatus();
				String statusMap = billMap.get(lstBill.get(i).getDescription())
						.getStatus();

				if ((Float.parseFloat(amountMap) + Float.parseFloat(amountBill) == 0) && periodBill.contentEquals(periodMap) && statusBill.contentEquals(statusMap)) {
					billMap.remove(lstBill.get(i).getDescription());
				} else {
					billMap.put(lstBill.get(i).getDescription() + "_" + i,
							lstBill.get(i));
				}
			} else {
				billMap.put(lstBill.get(i).getDescription(), lstBill.get(i));
			}
		}
		List<String> strStatusAndDate = new ArrayList<>();
		for (String billKey : billMap.keySet()) {
			System.out.println(billKey + "---->"
					+ billMap.get(billKey).getAmount() + "---->"
					+ billMap.get(billKey).getPeriod() + "---->"
					+ billMap.get(billKey).getStatus());
			Bill bill = billMap.get(billKey);
			separateDate(bill);
			if( (!strStatusAndDate.contains(bill.getStatus())) && (bill.getStatus() != null) && (bill.getStatus() != "" )){
				strStatusAndDate.add(billMap.get(billKey).getStatus());
				lstStatusAndDate.add(bill);
			}
			resultList.add(bill);
		}
		System.out.println("---------------------------------");

		return resultList;
	}
	
	public void calculateTotalAdjustment (ProrationDetails prorationDetails){
		float totalAdjustment = (float) 0 ;
		for(int i =0; i< prorationDetails.getLstCurrentBillCharges().size(); i++){
			totalAdjustment = totalAdjustment + convertFromRingToCent(Float.parseFloat(prorationDetails.getLstCurrentBillCharges().get(i).getAmount()));
		}
		for(int j=0 ; j < prorationDetails.getLstSubscriptionChanges().size(); j ++){
			totalAdjustment = totalAdjustment + convertFromRingToCent(Float.parseFloat(prorationDetails.getLstSubscriptionChanges().get(j).getAmount()));
		}
		
		prorationDetails.setTotalAdjustment(Float.toString(totalAdjustment/100));
	}
	
	
	public Float convertFromRingToCent(Float number){
		return number*100;
	}
	
//	public void getListDate(ProrationDetails prorationDetails) {
////		SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yy");
//		SimpleDateFormat sdf2  = new SimpleDateFormat("yyyy,MM,dd");
//		List<Date> lstDate = new ArrayList<>();
//		List<String> lstStrDate = new ArrayList<>();
//		HashMap<String, String> dateMap = new HashMap<>();
//		for (int i = 0; i < prorationDetails.getLstCurrentBillCharges().size(); i++) {
//			if (!dateMap.containsKey(prorationDetails
//					.getLstCurrentBillCharges().get(i).getStartDate())) {
//				dateMap.put(prorationDetails.getLstCurrentBillCharges().get(i)
//						.getStartDate(), prorationDetails
//						.getLstCurrentBillCharges().get(i).getStartDate());
//			}
//			if (!dateMap.containsKey(prorationDetails
//					.getLstCurrentBillCharges().get(i).getEndDate())) {
//				dateMap.put(prorationDetails.getLstCurrentBillCharges().get(i)
//						.getEndDate(), prorationDetails
//						.getLstCurrentBillCharges().get(i).getEndDate());
//			}
//		}
//		for (int i = 0; i < prorationDetails.getLstSubscriptionChanges().size(); i++) {
//			if (!dateMap.containsKey(prorationDetails
//					.getLstSubscriptionChanges().get(i).getStartDate())) {
//				dateMap.put(prorationDetails.getLstSubscriptionChanges().get(i)
//						.getStartDate(), prorationDetails
//						.getLstSubscriptionChanges().get(i).getStartDate());
//			}
//			if (!dateMap.containsKey(prorationDetails
//					.getLstSubscriptionChanges().get(i).getEndDate())) {
//				dateMap.put(prorationDetails.getLstSubscriptionChanges().get(i)
//						.getEndDate(), prorationDetails
//						.getLstSubscriptionChanges().get(i).getEndDate());
//			}
//		}
//		try {
//			for (String key : dateMap.keySet()) {
//				lstDate.add(sdf2.parse(dateMap.get(key)));
//
//			}
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
//		Collections.sort(lstDate);
//		for (int i = 0; i < lstDate.size(); i++) {
//			lstStrDate.add(sdf2.format(lstDate.get(i)));
//		}
//		prorationDetails.setLstDate(lstStrDate);
//	}
	
	public void separateDate(Bill bill){
		Date strStartDate = new Date();
		Date strEndDate = new Date();
		try{
			strStartDate = sdf.parse(bill.getPeriod().substring(0,bill.getPeriod().indexOf("-")));
			strEndDate = sdf.parse(bill.getPeriod().substring(bill.getPeriod().indexOf("-")+1));
			if(!lstTempDate.contains(strEndDate) ){
				lstTempDate.add(strEndDate);
			}
			if(!lstTempDate.contains(strStartDate) && !bill.getStatus().isEmpty()){
				lstTempDate.add(strStartDate);
			}
			
		}catch (Exception ex){
			ex.printStackTrace();
		}
        
		bill.setStartDate(minusMonth(sdf2.format(strStartDate)));
		bill.setEndDate(minusMonth(sdf2.format(strEndDate)));
	}
	public String minusMonth(String lstDate){
		String tempDate = "";
		String tempMonth = "";
			tempDate = lstDate;
			tempMonth = tempDate.substring(tempDate.indexOf(",")+1, tempDate.lastIndexOf(","));
			tempMonth = Integer.toString(Integer.parseInt(tempMonth) - 1);
			tempDate = lstDate.substring(0, lstDate.indexOf(",")) + "," + tempMonth + lstDate.substring(lstDate.lastIndexOf(","));
			return tempDate;
	}
}